<?php

namespace yan\googlebusiness\factory;

use Exception;
define('STDIN', fopen('php://stdin', 'r'));

class Authenticate extends \yan\googlebusiness\AbstractFactory
{
    const OAUTH_TOKEN_FILE_NAME = 'stored-token.json';

    public function init(){

    }
    private function getToken($client)
    {
        $authCode = trim(fgets(STDIN));
        if(isset($_GET['code']) && !empty($_GET['code'])){
            $authCode = $_GET['code'];
        }
        $redirect_uri = $this->getService()->getRedirectUri();
        if(empty($redirect_uri)){
            $redirect_uri = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == "on") ? "https" : "http"). "://". @$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
        }
        $client->setRedirectUri($redirect_uri);
        $client->setScopes('https://www.googleapis.com/auth/content');
        $client->setAccessType('offline'); // So that we get a refresh token

        if(empty($authCode)){
            // $client->setRedirectUri('urn:ietf:wg:oauth:2.0:oob');
            
            // Request authorization from the user.
            $_SESSION['code_verifier'] = $client->getOAuth2Service()->generateCodeVerifier();
            $authUrl = $client->createAuthUrl();
            // printf("Open the following link in your browser:\n%s\n", $authUrl);
            
            header('Location: ' . filter_var($authUrl, FILTER_SANITIZE_URL));
            exit;
        }
        // Exchange authorization code for an access token.
        $accessToken = $client->fetchAccessTokenWithAuthCode($authCode, $_SESSION['code_verifier']);

        // Check to see if there was an error.
        if (array_key_exists('error', $accessToken)) {
            throw new \Exception(join(', ', $accessToken));
        }
        $client->setAccessToken($accessToken);

        // $code = trim(fgets(STDIN));
        // $client->authenticate($code);

        return $client->getAccessToken();
    }

    protected function cacheToken($client)
    {
        $tokenFile = join(
            DIRECTORY_SEPARATOR,
            [dirname(dirname(__DIR__)), self::OAUTH_TOKEN_FILE_NAME]
        );
        if (file_exists($tokenFile)) {
            $accessToken = json_decode(file_get_contents($tokenFile), true);
            if(!empty($accessToken)){
                $client->setAccessToken($accessToken);
            }
        }
        if ($client->isAccessTokenExpired()) {
            // Refresh the token if possible, else fetch a new one.
            if ($client->getRefreshToken()) {
                $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
            } else {
                
                $token = $this->getToken($client);
                
            }
            // Save the token to a file.
            if (!file_exists(dirname($tokenFile))) {
                mkdir(dirname($tokenFile), 0700, true);
            }
            file_put_contents($tokenFile, json_encode($client->getAccessToken()));
        }
    }
    public function authenticate($client)
    {
        $this->authenticateFromConfig($client);
    }
    // Handles loading authentication credentials from the config dir.
    protected function authenticateFromConfig($client)
    {
        
        $tokenFile = join(
            DIRECTORY_SEPARATOR,
            [$this->getService()->getRootDir(), self::OAUTH_TOKEN_FILE_NAME]
        );
        $token = null;
        if (file_exists($tokenFile)) {
            $token = json_decode(file_get_contents($tokenFile), true);
        }
        if (is_null($token) || !array_key_exists('refresh_token', $token)) {
            $this->cacheToken($client);
        } else {
            try {
                $client->refreshToken($token['refresh_token']);
            } catch (\Exception $exception) {
                $this->cacheToken($client);
            }
        }
        return;
    }
}
